I own a Thinkpad X220 and the fan is sometimes annoying me. Even when the system is idle, a load average around 0.2 and the CPU is scaled down to the lowest frequency, the fan is spinning at a hearable noise.
So I wondered whether it's possible to tune the cooling algorithm and software control the fan. Short answer: yes, it's possible.
A quick internet search brings up sites and projects like:
The Thinkwiki describes the procfs interface /proc/acpi/ibm/
, but the linux kernel driver should also support the newer sysfs
interface. A quick look into the kernel sources thinkpad_acpi.c shows that it really supports the new sysfs fan and temperature controls.
On my system the fan can be queried and controlled by the sys files
$ ls /sys/devices/platform/thinkpad_hwmon/hwmon/hwmon3
device fan1_input name power pwm1 pwm1_enable subsystem uevent
And the temperature can be read from the two sysfs directories
$ ls /sys/devices/virtual/thermal/thermal_zone0
available_policies k_d mode power temp uevent
device k_i offset slope trip_point_0_temp
hwmon1 k_po passive subsystem trip_point_0_type
integral_cutoff k_pu policy sustainable_power type
$ ls /sys/devices/virtual/thermal/thermal_zone1
available_policies k_po power temp trip_point_1_type
integral_cutoff k_pu slope trip_point_0_temp type
k_d offset subsystem trip_point_0_type uevent
k_i policy sustainable_power trip_point_1_temp
I don't know where the two temperature sensors are located on the mainboard, but most of the time they report a similar value:
$ cat /sys/devices/virtual/thermal/thermal_zone0/temp
49000
$ cat /sys/devices/virtual/thermal/thermal_zone1/temp
50000
To be able to software control the fan, you have to set a kernel module parameter thinkpad_acpi.fan_control
:
$ cat /etc/default/grub
GRUB_CMDLINE_LINUX="init=/usr/lib/systemd/systemd thinkpad_acpi.fan_control=1"
[…]
$ sudo grub-mkconfig -o /boot/grub/grub.cfg
$ reboot
Just a safe guard to avoid accidentally damaging your system. You have to explicitly opt-in for that feature.
Reading the kernel sources of the driver provides a very good overview about the capabilities of the fan controls exposed in the sysfs:
/*
* SYSFS fan layout: hwmon compatible (device)
*
* pwm*_enable:
* 0: "disengaged" mode
* 1: manual mode
* 2: native EC "auto" mode (recommended, hardware default)
*
* pwm*: set speed in manual mode, ignored otherwise.
* 0 is level 0; 255 is level 7. Intermediate points done with linear
* interpolation.
*
* fan*_input: tachometer reading, RPM
*
*
* SYSFS fan layout: extensions
*
* fan_watchdog (driver):
* fan watchdog interval in seconds, 0 disables (default), max 120
*/
So there are three operation modes: disengaged, manual and auto. We only consider the modes manual and auto in this text. The hardware supports seven different levels that are mapped into the integer range 0 to 255. The mapping is:
level 0 -> value 0
level 1 -> value 36
level 2 -> value 72
level 3 -> value 109
level 4 -> value 145
level 5 -> value 182
level 6 -> value 218
level 7 -> value 255
You can exercise the sysfs interface with shell commands. So experiments are easy:
# Set the fan into manual mode
$ echo 1 > /sys/devices/platform/thinkpad_hwmon/hwmon/hwmon3/pwm1_enable
# Set the fan speed to level 5
$ echo 182 > /sys/devices/platform/thinkpad_hwmon/hwmon/hwmon3/pwm1
# Spin down the fan completely
$ echo 0 > /sys/devices/platform/thinkpad_hwmon/hwmon/hwmon3/pwm1
# Switch back to auto mode
$ echo 2 > /sys/devices/platform/thinkpad_hwmon/hwmon/hwmon3/pwm1_enable
When playing with fan settings it is a good backup to keep an eye the CPU temperature. Otherwise the system may get too hot. To do this just use something like
$ while true; do \
cat /sys/devices/virtual/thermal/thermal_zone0/temp; \
sleep 1; \
done
in a second shell.
Question: Which fan speed level is which RPM value?
The actual fan speed in RPMs can be queried from the file
$ cat /sys/devices/platform/thinkpad_hwmon/hwmon/hwmon3/fan1_input
3676
So my first question was: What is the fan speed in RPMs when I set a specific fan level?
After some python scripting, logging and gnuplot magic, I got this output data
| Fan level | Median
--+-----------+--------
0 | 0 | 0
1 | 36 | 1948
2 | 72 | 3112
3 | 109 | 3642
4 | 145 | 3642
5 | 182 | 4017
6 | 218 | 4026
7 | 255 | 4609
and this graph:
The interesting observation is that the seven fan levels actually map to only five different RPM values. Fan levels three and four and fan levels five and six, actually correspond to the same RPM values 3642 and ~4020.
Question: How does auto mode algorithm works?
After knowing more about the hardware capabilities of the fan the next question is the behavior of the fan in auto mode. How and which fan level does it choose?
My basic assumption is that it's a linear function bound to the temperature of the system.
When the fan is in auto mode it's not possible to read back the fan level. Reading from the sys file
/sys/devices/platform/thinkpad_hwmon/hwmon/hwmon3/pwm1
yields always the same value, even when I hear that the fan is changing it's speed level. So I tried to indirectly observe the speed level from the RPM value.
After some additional logging of the system under idle and high load conditions (portage updates) and gnuplotting, I got the following graph:
There are again five clusters clearly visible. I didn't expected the clusters to be sharp, because the algorithm and the fan needs some time to react to the temperature changes and ramp up or down the speed.
Even so there are five clusters, not every cluster is equal in the amount of datapoints. There are two big and three smaller clusters. The big clusters are RPM values 3642 and 4609. This can be an artifact from the testing conditions. The system was either in a high load condition (compiling software projects) or idle.
What stands out is the fact that even when the system was idle, the fan speed remained at levels three or four (= RPM value 3642). There are a lot of datapoints for these fan levels even so the temperature of the system is less than 50°C. The lower fan levels (zero, one and two) are hardly used.
This result also fits my day to day observations. For example currently the fan spins hearable with 3654 RPMs (levels 3 and 4), even so CPU temperature is around ~50°C.
Back to the question: Does the auto algorithm use a linear function to set the fan level? For now I don't have a definite answer. The graph does not show it. Maybe there are also other system properties that the algorithm takes into consideration.
Conclusion
When the hardware is controlling the fan speed level in auto mode, it does not utilize the lower fan speed levels in my setup. It would be really nice, if the fan would spin down to the lowest mode possible to keep the temperature. It does not have spin down completely. Even the lowest spinning mode, level one (=RPM value 1948), is not hearable.
Using a userspace software daemon to control the fan and implement this better behavior, is a task for another story.